#include "mainui.h"
#include <QCoreApplication>
#include <QApplication>
#include <QProcess>
#include <QWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QComboBox>
#include <QPushButton>
#include <QScrollArea>
#include <QProgressDialog>
#include <QFile>
#include <QScreen>

#include <QToolButton>
#include "message.h"

class MinLengthValidator : public QValidator {
public:
    MinLengthValidator(unsigned long long min) : m_min(min) {}

    State validate(QString &input, int &pos) const override {
        if ((quint64)input.length() < m_min) {
            input = ""; // 清空输入内容
                        return Invalid;
        } else {
            return Acceptable; // 输入长度满足要求，返回Acceptable状态
        }
    }
private:
    unsigned long m_min;
};

class ULongRangeValidator : public QValidator {
public:
    ULongRangeValidator(unsigned long long min, unsigned long long max) : m_min(min), m_max(max) {}

    State validate(QString &input, int &pos) const override {
        bool ok;
        unsigned long long value = input.toULongLong(&ok);
        if (ok && value >= m_min && value <= m_max) {
            return Acceptable;
        } else {
            input = ""; // 清空输入内容
                        return Invalid;
        }
    }

private:
    unsigned long m_min;
    unsigned long m_max;
};

MainUi::MainUi(QObject *parent) : QObject(parent)
{
    MainWidget = new QWidget();
    MainWidget->setWindowTitle("Setup");
    tabWidget  = new QTabWidget(MainWidget);
    saveButton = new QPushButton();
    mainLayout = new QVBoxLayout(MainWidget);

    AdvanceBox = NULL;
    BootBox = NULL;
    SecurityBox = NULL;
    MainBox = NULL;
    Save_ExitBox = NULL;
    SearchBox = NULL;

    QObject::connect(saveButton, &QPushButton::clicked, [this]{
        Json->SaveCfg();
        ImportCfgShow();
    });

    saveButton->setText("导入");
    mainLayout->addWidget(tabWidget);
    mainLayout->addWidget(saveButton);
    MainWidget->setLayout(mainLayout);

    GetPlatInfo();
}

void MainUi::ImportCfgShow(void)
{
    Dialog = new QProgressDialog("正在导入，请稍后...", nullptr, 0, 100);
    Dialog->setWindowTitle("导入");

    Dialog->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint);
    Dialog->setWindowState(Qt::WindowNoState);
    Dialog->setModal(true);
    Dialog->setCancelButton(nullptr);

    Processconnect = QObject::connect(&Setup, &SetupThread::ProcessNotify, [this](int progress){
         if (100 != progress)
         {
              Dialog->setValue(progress/2);
         }
         else
         {
             timecnt = 0;
             disconnect(Processconnect);
             timer.start(MAXWAIT);
         }
     });

    timeconnect = QObject::connect(&timer, &QTimer::timeout, [this]() {
        timecnt++;
        Dialog->setValue(50 + (timecnt/2));
        if (timecnt == 100)
        {
            timer.stop();
            Dialog->close();
            delete Dialog;
            message CMessage;
            CMessage.showtips("导入失败");
            CMessage.setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
            CMessage.exec();
        }

    });

    //QObject::connect(&Setup, &SetupThread::ResultNotify, Dialog, &QProgressDialog::cancel);
    connection = QObject::connect(&Setup, &SetupThread::ResultNotify,  QCoreApplication::instance(), [this](QString result){
        Dialog->setValue(100);
        Dialog->close();
        //disconnect(&Setup, &SetupThread::ResultNotify, Dialog, &QProgressDialog::cancel);
        disconnect(connection);
        disconnect(timeconnect);
        timer.stop();
        delete Dialog;
        message CMessage;
        CMessage.showtips(result);
        CMessage.setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
        CMessage.exec();
    });

    Dialog->show();

    QString cmd = PlatInfo;
    cmd = cmd.append(" import");
    Setup.SetCmdPar(cmd);
    Setup.start();

    Dialog->exec();
}

void MainUi::GetPlatInfo(void)
{
    if (!Setup.GetPlatInfo())
    {
        QWidget* platWidget = new QWidget();
        platWidget->setWindowTitle("平台信息");
        //platWidget->setAttribute(Qt::WA_DeleteOnClose);
        QVBoxLayout* platLayout = new QVBoxLayout(platWidget);
        QLabel *label = new QLabel("请选择平台");
        platLayout->addWidget(label);
        QComboBox *combo = new QComboBox;
        foreach(QString Plat, PlatList){
         combo->addItem(Plat);
        }

        platLayout->addWidget(combo);
        QPushButton *Button = new QPushButton(QString::fromUtf8("确定"));
        QObject::connect(Button, &QPushButton::clicked, [platWidget, combo, PlatInfo = &PlatInfo]{
            PlatInfo->clear();
            PlatInfo->append("--plat=");
            PlatInfo->append(combo->currentText());

            platWidget->close();
        });

        platLayout->addWidget(Button);

        /* 取消最大化，最小化和关闭 */
        platWidget->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
        platWidget->setWindowState(Qt::WindowNoState);
        platWidget->show();
        QCoreApplication::exec();
        delete platWidget;
    }
}

void MainUi::ExportShow(void)
{
    Dialog = new QProgressDialog("正在读取，请稍后...", nullptr,  0, 100);
    Dialog->setWindowTitle("导出");
    Dialog->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint);
    Dialog->setWindowState(Qt::WindowNoState);
    Dialog->setModal(true);
    Dialog->setCancelButton(nullptr);

    /* 保证导出后对话框关闭 */
   Processconnect = QObject::connect(&Setup, &SetupThread::ProcessNotify, [this](int progress){
        if (100 == progress)
        {
            Dialog->setLabelText("正在解析，请稍后...");
            Dialog->setValue(0);
            timecnt = 0;
            timer.start(MAXWAIT);
        }
        else
        {
            Dialog->setValue(progress);
        }

    });

    timeconnect = QObject::connect(&timer, &QTimer::timeout, [this]() {
        timecnt++;
        Dialog->setValue(timecnt);
        if (timecnt == 100)
        {
            message CMessage;
            CMessage.showtips("解析失败");
            CMessage.setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
            CMessage.exec();
            std::exit(1);
        }

    });

    //QObject::connect(&Setup, &SetupThread::ResultNotify, Dialog, &QProgressDialog::cancel);
    connection = QObject::connect(&Setup, &SetupThread::ResultNotify,  QCoreApplication::instance(), [this](QString result){
        Dialog->setValue(100);
       // disconnect(&Setup, &SetupThread::ResultNotify, Dialog, &QProgressDialog::cancel);
        disconnect(Processconnect);
        disconnect(timeconnect);
        disconnect(connection);
        timer.stop();
        delete Dialog;

        if (!result.contains("成功"))
        {
            message CMessage;
            CMessage.showtips(result);
            CMessage.setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
            CMessage.exec();
            std::exit(1);
        }
    });

    Dialog->show();
    QString cmd = PlatInfo;
    cmd = cmd.append(" export");
    Setup.SetCmdPar(cmd);
    Setup.start();
    Dialog->exec();
}

quint8 MainUi::ParseCfgShow(void)
{
    QByteArray jsonData;
    QString QStrDir = QString("%1").arg(QCoreApplication::applicationDirPath());;
    QStrDir.append("/config/config");
    QFile Cfile(QStrDir);
    if (false == Cfile.open(QFile::ReadOnly))
    {
        qDebug("Open config File %s fail", QStrDir.toStdString().c_str());
        return 1;
    }

    jsonData = Cfile.readAll();
    Json = new JsonPrase(jsonData);
    Dialog = new QProgressDialog("正在生成界面，请稍后...", nullptr, 0, 100);
    Dialog->setWindowTitle("界面生成");
    Dialog->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint);
    Dialog->setWindowState(Qt::WindowNoState);
    Dialog->setModal(true);
    Dialog->setCancelButton(nullptr);
    Dialog->show();
    return 0;
}

void MainUi::MainUiShow(void)
{
    u32FormIndex = 0;
    QList<Form>& TmpForms = Json->FormGet();
    timeconnect = QObject::connect(&timer, &QTimer::timeout, [&TmpForms, this]() { 
        static int progress = 0;
        if (0 != TmpForms.size())
        {
            progress = 100 * (u32FormIndex) / TmpForms.size();
        }
        else{
            timer.stop();
            Dialog->close();
            delete Dialog;
            message CMessage;
            CMessage.showtips("配置文件解析错误");
            CMessage.setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
            CMessage.exec();
            std::exit(1);
        }

        Dialog->setValue(progress);
        if (progress >= 100) {

            disconnect(timeconnect);
            timer.stop();
            Dialog->close();
            delete Dialog;
            MainWidget->show();
            return;
        }

        QVBoxLayout *LayOut = FormCreate(TmpForms[u32FormIndex].QStrName);
        QList<SubForm>& TmpSubForms = Json->SubFormGet(&TmpForms[u32FormIndex]);
        for (quint32 u32SubFormIndex = 0; u32SubFormIndex < (quint32)TmpSubForms.size(); u32SubFormIndex++)
        {
            QGridLayout* configLayout = SubFormCreate(LayOut, TmpSubForms[u32SubFormIndex].QStrName);
            QList<VariableObj>& TmpVar = Json->VarGet(&TmpSubForms[u32SubFormIndex]);
            for (quint32 u32VarIndex = 0; u32VarIndex < (quint32)TmpVar.size(); u32VarIndex++)
            {
                QList<OptionCfg>& TmpCfg = Json->ConfigGet(&TmpVar[u32VarIndex]);
                for (quint32 u32CfgIndex = 0; u32CfgIndex < (quint32)TmpCfg.size(); u32CfgIndex++)
                {
                    OptionCfg* pstcfg = &TmpCfg[u32CfgIndex];
                    switch(TmpCfg[u32CfgIndex].enType)
                    {
                        case CHECK:
                        {
                            CheckBoxCreate(configLayout, pstcfg);
                            break;
                        }

                        case NUM:
                        {
                            NumCfgCreate(configLayout, pstcfg);
                            break;
                        }

                        case OPTION:
                        {
                            OptionCfgCreate(configLayout, pstcfg);
                            break;
                        }

                        case STRING:
                        {
                            StrCfgCreate(configLayout, pstcfg);
                            break;
                        }

                        case LIST:
                        {

                            ListCfgCreate(configLayout, pstcfg);
                            break;
                        }
                    }
                }
            }
        }

        u32FormIndex++;
    });

    timer.start(10);
}

/* 一级界面初始化 */
void MainUi::FormSetInit(QVBoxLayout **Layout, QString FormSetName)
{
    if (*Layout != NULL)
        return;

    QWidget* page  = new QWidget();
    *Layout = new QVBoxLayout(page);
    //page->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    QScrollArea* scrollArea = new QScrollArea();
    scrollArea->setWidget(page);
    scrollArea->setWidgetResizable(true);

    page->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    page->setLayout((*Layout));
    (*Layout)->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    (*Layout)->setSpacing(0);

    tabWidget->addTab(scrollArea, FormSetName);
}

QVBoxLayout * MainUi::FormCreate(QString FormName)
{
    if (FormName == MAIN)
    {
        FormSetInit(&MainBox, MAIN);
        return MainBox;
    }
    else if (FormName == ADVANCE)
    {
        FormSetInit(&AdvanceBox, ADVANCE);
        return AdvanceBox;
    }
    else if (FormName == BOOT)
    {
        FormSetInit(&BootBox, BOOT);
        return BootBox;
    }
    else if (FormName == SECURITY)
    {
        FormSetInit(&SecurityBox, SECURITY);
        return SecurityBox;
    }
    else if (FormName == Search)
    {
        FormSetInit(&SearchBox, Search);
        return SearchBox;
    }
    else if ((FormName == SAVE_EXIT) || (FormName == SAVE_EXIT_1))
    {
        FormSetInit(&Save_ExitBox, SAVE_EXIT);
        return Save_ExitBox;
    }
    else if (FormName == SETUP)
    {
        /* FormName为Setup为旧模式，判断在subform中处理，直接返回空 */
        FormSetInit(&AdvanceBox, ADVANCE);
        FormSetInit(&BootBox, BOOT);
        FormSetInit(&SecurityBox, SECURITY);

        return NULL;
    }

    QWidget* page  = new QWidget();
    page->hide();
    page->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    page->setObjectName("parentWidget");
    page->setStyleSheet("QWidget#parentWidget { border: 1px solid black; }");
    //QScrollArea* scrollArea = new QScrollArea();
    //scrollArea->setWidget(page);
   // scrollArea->setWidgetResizable(true);
    //scrollArea->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
   // scrollArea->hide();

    QVBoxLayout* subLayout = new QVBoxLayout(page);
    subLayout->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    subLayout->setSpacing(0);
    page->setLayout(subLayout);

    QPushButton *Button = new QPushButton(FormName);
    Button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
    Button->setStyleSheet("text-align:left;");
    //Button->setStyleSheet("border: none;");
    QObject::connect(Button, &QPushButton::clicked, [page]() {
        if (page->isHidden()){
            page->show();
        }else{
            page->hide();
        }
    });


    if (FormName.contains(BOOTODER))
    {
        FormSetInit(&BootBox, BOOT);
        BootBox->addWidget(Button);
        BootBox->addWidget(page);
    }
    else if (PLATHARDMON == FormName)
    {
        FormSetInit(&SecurityBox, SECURITY);
        SecurityBox->addWidget(Button);
        SecurityBox->addWidget(page);
    }
    else
    {
        FormSetInit(&AdvanceBox, ADVANCE);
        AdvanceBox->addWidget(Button);
        AdvanceBox->addWidget(page);
    }

    return subLayout;
}

QGridLayout *MainUi::SubFormCreate(QVBoxLayout *Layout, QString SubFormName){

    QWidget* page = new QWidget();
    QGridLayout* configLayout = new QGridLayout(page);
    page->hide();
    page->setObjectName("parentWidget");
    page->setStyleSheet("QWidget#parentWidget { border: 1px solid black; }");
    page->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);

   // QScrollArea* scrollArea = new QScrollArea();
    //scrollArea->setWidget(page);
   // scrollArea->setWidgetResizable(true);
   // scrollArea->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
   // scrollArea->hide();

    QPushButton *Button = new QPushButton(SubFormName);
    Button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
    Button->setStyleSheet("text-align:left;");
    //Button->setStyleSheet("border: none;");
    QObject::connect(Button, &QPushButton::clicked, [page]() {
        if (page->isHidden()){
            page->show();
        }else{
            page->hide();
        }
    });

    /* 如果为NULL，证明bios为旧版，这里需要做Boot，Advance等的判断 */
    if (Layout == NULL)
    {
        if (SubFormName.contains(BOOT) || SubFormName.contains(BOOTODER))
        {
            BootBox->addWidget(Button);
            BootBox->addWidget(page);
        }
        else if (SubFormName.contains(SECURITY))
        {
            SecurityBox->addWidget(Button);
            SecurityBox->addWidget(page);
        }
        else
        {
            AdvanceBox->addWidget(Button);
            AdvanceBox->addWidget(page);
        }
    }
    else{

        Layout->addWidget(Button);
        Layout->addWidget(page);
    }

    configLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    page->setLayout(configLayout);

    ulConfigIndex = 0;
    return configLayout;
}

void MainUi::CheckBoxCreate(QGridLayout *CfgLayout, OptionCfg* pstcfg)
{
    QLabel *helplabel = new QLabel(pstcfg->QStrhelp);
    helplabel->setWordWrap(true);
    QCheckBox *checkBox = new QCheckBox(pstcfg->QStrName);
    checkBox->setChecked((bool)pstcfg->value.toInt());

    QObject::connect(checkBox, &QCheckBox::stateChanged, [Json = Json, pstcfg, checkBox]() {
        Json->ConfigSet(pstcfg, checkBox->checkState());
    });

    CfgLayout->addWidget(checkBox, ulConfigIndex, 0);
    CfgLayout->setAlignment(checkBox, Qt::AlignLeft);
    CfgLayout->addWidget(helplabel, ulConfigIndex, 1);
    CfgLayout->setAlignment(helplabel, Qt::AlignLeft);
    helplabel->setMinimumHeight(helplabel->sizeHint().height());
    ulConfigIndex++;
    return;
}

void MainUi::NumCfgCreate(QGridLayout *CfgLayout, OptionCfg* pstcfg)
{
    QLabel *label = new QLabel(pstcfg->QStrName);
    QLabel *helplabel = new QLabel(pstcfg->QStrhelp);
    helplabel->setWordWrap(true);
    QLineEdit *lineEdit = new QLineEdit;

    lineEdit->setFixedWidth(2 * lineEdit->fontMetrics().width(QString::number(pstcfg->u64Max)));
    lineEdit->setValidator(new ULongRangeValidator(pstcfg->u64Min, pstcfg->u64Max));
    lineEdit->setText(QString::number(pstcfg->u64val));

    QObject::connect(lineEdit, &QLineEdit::textChanged, [Json = Json, pstcfg, lineEdit]() {
        Json->ConfigSet(pstcfg, lineEdit->text().toULongLong());
    });

    CfgLayout->addWidget(label, ulConfigIndex, 0);
    CfgLayout->setAlignment(label, Qt::AlignLeft);
    CfgLayout->addWidget(lineEdit, ulConfigIndex, 1);
    CfgLayout->setAlignment(lineEdit, Qt::AlignLeft);
    CfgLayout->addWidget(helplabel, ulConfigIndex, 2);
    CfgLayout->setAlignment(helplabel, Qt::AlignLeft);
    helplabel->setMinimumHeight(helplabel->sizeHint().height());
    ulConfigIndex++;
    return;
}

void MainUi::OptionCfgCreate(QGridLayout *CfgLayout, OptionCfg* pstcfg)
{
    QLabel *label = new QLabel(pstcfg->QStrName);
    QLabel *helplabel = new QLabel(pstcfg->QStrhelp);
    helplabel->setWordWrap(true);
    QComboBox *combo = new QComboBox;

    for (QHash<QString, quint64>::const_iterator i = pstcfg->Option.constBegin(); i != pstcfg->Option.constEnd(); i++)
    {
        combo->addItem(i.key());
        if (pstcfg->u64val == (quint64)i.value())
        {
           combo->setCurrentText(i.key());
        }
    }

    /* boot order不能重复 */
    QRegularExpression regex("Boot Option #?(\\d+)");
    QRegularExpressionMatch match = regex.match(pstcfg->QStrName);
    if (match.hasMatch()) {
         BootOpList.append(QPair<QComboBox *, QString>(combo, combo->currentText()));
         u8BootIndex = BootOpList.size() - 1;
    }
    else
    {
        u8BootIndex = 0xff;
    }

    QObject::connect(combo, QOverload<const QString &>::of(&QComboBox::currentIndexChanged), [this, pstcfg, u8Index = u8BootIndex, combo]() {
        QString TmpStr =  combo->currentText();
        qDebug("%s", TmpStr.toStdString().c_str());
        for (QHash<QString, quint64>::const_iterator i = pstcfg->Option.constBegin(); i != pstcfg->Option.constEnd(); i++)
        {
            if (TmpStr == i.key())
            {
                Json->ConfigSet(pstcfg, i.value());
            }
        }

        if (u8Index == 0xff)
        {
            return;
        }

        for (QList<QPair<QComboBox *, QString>>::const_iterator i = BootOpList.begin(); i != BootOpList.end(); i++)
        {

            if (TmpStr == i->second)
            {
               /* 已经改变的就不用改变了 */
               if (i->first->currentText() == BootOpList[u8Index].second)
               {
                   break;
               }

               i->first->setCurrentText(BootOpList[u8Index].second);
            }
        }

        BootOpList[u8Index].second = TmpStr;
    });

    CfgLayout->addWidget(label, ulConfigIndex, 0);
    CfgLayout->setAlignment(label, Qt::AlignLeft);
    CfgLayout->addWidget(combo, ulConfigIndex, 1);
    CfgLayout->setAlignment(combo, Qt::AlignLeft);
    CfgLayout->addWidget(helplabel, ulConfigIndex, 2);
    CfgLayout->setAlignment(helplabel, Qt::AlignLeft);
    helplabel->setMinimumHeight(helplabel->sizeHint().height());
    ulConfigIndex++;
    return;

}

void MainUi::StrCfgCreate(QGridLayout *CfgLayout, OptionCfg* pstcfg)
{
    QLabel *label = new QLabel(pstcfg->QStrName);
    QLabel *helplabel = new QLabel(pstcfg->QStrhelp);
    helplabel->setWordWrap(true);
    QLineEdit *lineEdit = new QLineEdit;

    lineEdit->setFixedWidth(2 * lineEdit->fontMetrics().width("w") * pstcfg->u64Max);
    lineEdit->setMaxLength(pstcfg->u64Max);
    lineEdit->setValidator(new MinLengthValidator(pstcfg->u64Min));
    lineEdit->setText(pstcfg->value.toString());

    QObject::connect(lineEdit, &QLineEdit::textChanged, [Json = Json, pstcfg, lineEdit]() {
        Json->ConfigSet(pstcfg, lineEdit->text());
     });

    CfgLayout->addWidget(label, ulConfigIndex, 0);
    CfgLayout->setAlignment(label, Qt::AlignLeft);
    CfgLayout->addWidget(lineEdit, ulConfigIndex, 1);
    CfgLayout->setAlignment(lineEdit, Qt::AlignLeft);
    CfgLayout->addWidget(helplabel, ulConfigIndex, 2);
    CfgLayout->setAlignment(helplabel, Qt::AlignLeft);
    helplabel->setMinimumHeight(helplabel->sizeHint().height());

    ulConfigIndex++;
    return;
}

void MainUi::ListCfgCreate(QGridLayout *CfgLayout, OptionCfg* pstcfg)
{
    QLabel *label = new QLabel(pstcfg->QStrName);
    QLabel *helplabel = new QLabel(pstcfg->QStrhelp);
    helplabel->setWordWrap(true);

    // 创建一个 QListWidget 控件
    QListWidget *listWidget = new QListWidget();

    // 设置 QListWidget 的显示模式为列表模式
    listWidget->setViewMode(QListWidget::ListMode);

    // 允许用户编辑选项的顺序
    listWidget->setDragDropMode(QAbstractItemView::InternalMove);

    QJsonArray JsonArray = pstcfg->value.toArray();
    for (int row = 0; row < JsonArray.size(); ++row) {
        for (QHash<QString, quint64>::const_iterator i = pstcfg->Option.constBegin(); i != pstcfg->Option.constEnd(); i++)
        {
            if (((quint64)JsonArray[row].toDouble()) == i.value())
            {
                QListWidgetItem *item = new QListWidgetItem(i.key());
                listWidget->addItem(item);
                break;
            }
        }

    }

    CfgLayout->addWidget(label, ulConfigIndex, 0);
    CfgLayout->setAlignment(label, Qt::AlignLeft);
    CfgLayout->addWidget(listWidget, ulConfigIndex, 1);
    CfgLayout->setAlignment(listWidget, Qt::AlignLeft);
    CfgLayout->addWidget(helplabel, ulConfigIndex, 2);
    CfgLayout->setAlignment(helplabel, Qt::AlignLeft);
    helplabel->setMinimumHeight(helplabel->sizeHint().height());
    ulConfigIndex++;
    return;
}
